#pragma once
#include <string>
#include <map>
#include <set>
#include <iostream>

namespace html { namespace dom
{
  using namespace std;

  struct node;

  /// @brief string with additional quoting information. this is for
  /// remembering whether previously read quotes have to be written as
  /// ' or ".
  struct quoted_string : public string {
    /// @brief initializes with a string and a quote character
    quoted_string( const string& _text="", char _quote='\"' )
      : string( _text )
      , quote_(_quote)
    {}
    quoted_string( const char* _text, char _quote='\"' )
      : string( _text )
      , quote_(_quote)
    {}
    /// @brief set the contained string and quote character
    void set( const string& _text, char _quote)  {
      *this = _text;
      quote_=_quote;
    }
    /// @brief return the stored quote character
    char quote() const { return quote_; }
  private:
    /// @brief quote character
    char quote_;
  };
  struct attribute {
    attribute(symbol _name)
      : name_(_name)
    {}
    node operator= (const string& _text) const;
    node operator[] (node _node) const;
    node operator[] (const string& text_) const;
  private:
    symbol name_;
  };
  /// @brief attribute map that stores symbol -> attribute value
  typedef map<symbol, quoted_string> attrib_map;

  // tags
  const attribute A = "a";
  const attribute Abbr = "abbr";
  const attribute Acronym = "acronym";
  const attribute Address = "address";
  const attribute Applet = "applet";
  const attribute Area = "area";
  const attribute B = "b";
  const attribute Base = "base";
  const attribute Basefont = "basefont";
  const attribute Bdo = "bdo";
  const attribute Big = "big";
  const attribute Blockquote = "blockquote";
  const attribute Body = "body";
  const attribute Br = "br";
  const attribute Button = "button";
  const attribute Caption = "caption";
  const attribute Center = "center";
  const attribute Cite = "cite";
  const attribute Code = "code";
  const attribute Col = "col";
  const attribute Colgroup = "colgroup";
  const attribute Dd = "dd";
  const attribute Del = "del";
  const attribute Dfn = "dfn";
  const attribute Dir = "dir";
  const attribute Div = "div";
  const attribute Dl = "dl";
  const attribute Dt = "dt";
  const attribute Em = "em";
  const attribute Fieldset = "fieldset";
  const attribute Font = "font";
  const attribute Form = "form";
  const attribute Frame = "frame";
  const attribute Frameset = "frameset";
  const attribute H1 = "h1";
  const attribute H2 = "h2";
  const attribute H3 = "h3";
  const attribute H4 = "h4";
  const attribute H5 = "h5";
  const attribute H6 = "h6";
  const attribute Head = "head";
  const attribute Hr = "hr";
  const attribute Html = "html";
  const attribute I = "i";
  const attribute Iframe = "iframe";
  const attribute Img = "img";
  const attribute Input = "input";
  const attribute Ins = "ins";
  const attribute Isindex = "isindex";
  const attribute Kbd = "kbd";
  const attribute Label = "label";
  const attribute Legend = "legend";
  const attribute Li = "li";
  const attribute Link = "link";
  const attribute Map = "map";
  const attribute Menu = "menu";
  const attribute Meta = "meta";
  const attribute Noframes = "noframes";
  const attribute Noscript = "noscript";
  const attribute Object = "object";
  const attribute Ol = "ol";
  const attribute Optgroup = "optgroup";
  const attribute Option = "option";
  const attribute P = "p";
  const attribute Param = "param";
  const attribute Pre = "pre";
  const attribute Q = "q";
  const attribute S = "s";
  const attribute Samp = "samp";
  const attribute Script = "script";
  const attribute Select = "select";
  const attribute Small = "small";
  const attribute Span = "span";
  const attribute Strike = "strike";
  const attribute Strong = "strong";
  const attribute Style_tag = "style";
  const attribute Sub = "sub";
  const attribute Sup = "sup";
  const attribute Table = "table";
  const attribute Tbody = "tbody";
  const attribute Td = "td";
  const attribute Textarea = "textarea";
  const attribute Tfoot = "tfoot";
  const attribute Th = "th";
  const attribute Thead = "thead";
  const attribute Title = "title";
  const attribute Tr = "tr";
  const attribute Tt = "tt";
  const attribute U = "u";
  const attribute Ul = "ul";
  const attribute Var = "var";

  // attributes
  const attribute Accept = "accept";
  const attribute Accept_charset = "accept-charset";
  const attribute Accesskey = "accesskey";
  const attribute Action = "action";
  const attribute Align = "align";
  const attribute Alink = "alink";
  const attribute Alt = "alt";
  const attribute Archive = "archive";
  const attribute Axis = "axis";
  const attribute Background = "background";
  const attribute Bgcolor = "bgcolor";
  const attribute Border = "border";
  const attribute Cellpadding = "cellpadding";
  const attribute Cellspacing = "cellspacing";
  const attribute Char = "char";
  const attribute Charoff = "charoff";
  const attribute Charset = "charset";
  const attribute Checked = "checked";
  const attribute Class = "class";
  const attribute Classid = "classid";
  const attribute Clear = "clear";
  const attribute Codebase = "codebase";
  const attribute Codetype = "codetype";
  const attribute Color = "color";
  const attribute Cols = "cols";
  const attribute Colspan = "colspan";
  const attribute Compact = "compact";
  const attribute Content = "content";
  const attribute Coords = "coords";
  const attribute Data = "data";
  const attribute Datetime = "datetime";
  const attribute Declare = "declare";
  const attribute Defer = "defer";
  const attribute Disabled = "disabled";
  const attribute Enctype = "enctype";
  const attribute Event = "event";
  const attribute Face = "face";
  const attribute For = "for";
  const attribute Frameborder = "frameborder";
  const attribute Headers = "headers";
  const attribute Height = "height";
  const attribute Href = "href";
  const attribute Hreflang = "hreflang";
  const attribute Hspace = "hspace";
  const attribute Http_equiv = "http-equiv";
  const attribute Id = "id";
  const attribute Ismap = "ismap";
  const attribute Lang = "lang";
  const attribute Language = "language";
  const attribute Longdesc = "longdesc";
  const attribute Marginheight = "marginheight";
  const attribute Marginwidth = "marginwidth";
  const attribute Maxlength = "maxlength";
  const attribute Media = "media";
  const attribute Method = "method";
  const attribute Multiple = "multiple";
  const attribute Name = "name";
  const attribute Nohref = "nohref";
  const attribute Noresize = "noresize";
  const attribute Noshade = "noshade";
  const attribute Nowrap = "nowrap";
  const attribute Onblur = "onblur";
  const attribute Onchange = "onchange";
  const attribute Onclick = "onclick";
  const attribute Ondblclick = "ondblclick";
  const attribute Onfocus = "onfocus";
  const attribute Onkeydown = "onkeydown";
  const attribute Onkeypress = "onkeypress";
  const attribute Onkeyup = "onkeyup";
  const attribute Onload = "onload";
  const attribute Onmousedown = "onmousedown";
  const attribute Onmousemove = "onmousemove";
  const attribute Onmouseout = "onmouseout";
  const attribute Onmouseover = "onmouseover";
  const attribute Onmouseup = "onmouseup";
  const attribute Onreset = "onreset";
  const attribute Onselect = "onselect";
  const attribute Onsubmit = "onsubmit";
  const attribute Onunload = "onunload";
  const attribute Profile = "profile";
  const attribute Prompt = "prompt";
  const attribute Readonly = "readonly";
  const attribute Rel = "rel";
  const attribute Rev = "rev";
  const attribute Rows = "rows";
  const attribute Rowspan = "rowspan";
  const attribute Rules = "rules";
  const attribute Scheme = "scheme";
  const attribute Scope = "scope";
  const attribute Scrolling = "scrolling";
  const attribute Selected = "selected";
  const attribute Shape = "shape";
  const attribute Size = "size";
  const attribute Src = "src";
  const attribute Standby = "standby";
  const attribute Start = "start";
  const attribute Style = "style";
  const attribute Summary = "summary";
  const attribute Tabindex = "tabindex";
  const attribute Target = "target";
  const attribute Text = "text";
  const attribute Type = "type";
  const attribute Usemap = "usemap";
  const attribute Valign = "valign";
  const attribute Value = "value";
  const attribute Valuetype = "valuetype";
  const attribute Version = "version";
  const attribute Vlink = "vlink";
  const attribute Vspace = "vspace";
  const attribute Width = "width";  
} }
